from aiogram import Dispatcher, types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Text
from aiogram.dispatcher.filters.state import State, StatesGroup
from utils.db_api import quick_commands as commands

# Эти значения далее будут подставляться в итоговый текст, отсюда
# такая на первый взгляд странная форма прилагательных
IPSS_answers = {"никогда": 0, "реже, чем 1 раз из 5": 1, "реже, чем в половине случаев": 2,
                "примерно в половине случаев": 3,
                "более половины случаев": 4, "практически всегда": 5}
IPSS_answers_last = {
    "никогда": 0, "1 раз": 1, "2 раза": 2, "3 раза": 3, "4 раза": 4, "5 или более раз": 5
}
QoL_answers = {"очень хорошо": 0, "хорошо": 1, "удовлетворительно": 2,
               "смешанное чувство": 3, "неудовлетворительно": 4, "плохо": 5, "ужасно": 6}


class Rating(StatesGroup):
    waiting_for_answer_1 = State()
    waiting_for_answer_2 = State()
    waiting_for_answer_3 = State()
    waiting_for_answer_4 = State()
    waiting_for_answer_5 = State()
    waiting_for_answer_6 = State()
    waiting_for_answer_7 = State()
    waiting_for_answer_8 = State()


async def cmd_start(message: types.Message):
    try:
        user = await commands.select_user(message.from_user.id)
        if user.status == 'active':
            await message.answer(f'Привет {user.first_name}\n'
                                 f'Ты уже зарегистрирован')
            buttons_3 = [
                types.InlineKeyboardButton(text="Опрос", callback_data="quiz"),
                types.InlineKeyboardButton(text="Записаться на приём", callback_data="info"),
                types.InlineKeyboardButton(text="Подписаться",
                                           callback_data="sub"),
                types.InlineKeyboardButton(text="Info", callback_data="info_us"),
            ]
            keyboard_3 = types.InlineKeyboardMarkup(row_width=2)
            keyboard_3.add(*buttons_3)

            await message.answer(f'Вот, что я умею:\n'
                                 f'Сейчас Вы можете:\n'
                                 f'Пройти опрос, принятый урологами во всём мире как золотой стандарт.\n'
                                 f'Подписаться на информационную рассылку.\n'
                                 f'Узнать, как и куда записаться к специалисту.\n'
                                 f'Прочитать дополнительную информацию обо мне, проекте и наших правилах.',
                                 reply_markup=keyboard_3)
    except Exception:
        await commands.add_user(user_id=message.from_user.id,
                                first_name=message.from_user.first_name,
                                last_name=message.from_user.last_name,
                                username=message.from_user.username,
                                status='active',
                                gender='undefined',
                                age='undefined',
                                ipss_test=-1,
                                qol_test=-1,
                                subscribed=False)
        await start(message)
        # await message.answer('Ты успешно зарегистрирован')


async def start(message):
    buttons_1 = [
        types.InlineKeyboardButton(text="M", callback_data="word_3"),
        types.InlineKeyboardButton(text="Ж", callback_data="word_2"),
    ]
    # Благодаря row_width=2, в первом ряду будет две кнопки, а оставшаяся одна
    # уйдёт на следующую строку
    keyboard_1 = types.InlineKeyboardMarkup(row_width=2)
    keyboard_1.add(*buttons_1)

    await message.answer(
        "Пожалуйста, для начала выберите букву, которая Вам ближе, а также числовой диапазон.\nВаш выбор не повлияет "
        "на доступ к функциям бота и будет использован только для статистики")

    await message.answer("Буква", reply_markup=keyboard_1)


async def answer_start(message, state):
    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in IPSS_answers:
        keyboard.add(answer)
    await message.message.answer(f"Как часто в течение последнего месяца у Вас "
                                 f"было ощущение неполного опорожнения "
                                 f"мочевого пузыря после мочеиспускания?", reply_markup=keyboard)
    await state.set_state(Rating.waiting_for_answer_1.state)


async def answer1_chosen(message: types.Message, state: FSMContext):
    if message.text.lower() not in IPSS_answers:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer1=message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in IPSS_answers:
        keyboard.add(answer)
    await state.set_state(Rating.waiting_for_answer_2.state)
    await message.answer(f"В течение последнего месяца как часто у Вас "
                         f"имелось прерывистое мочеиспускание?", reply_markup=keyboard)


async def answer2_chosen(message: types.Message, state: FSMContext):
    if message.text.lower() not in IPSS_answers:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer2=message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in IPSS_answers:
        keyboard.add(answer)
    await state.set_state(Rating.waiting_for_answer_3.state)
    await message.answer(f"Как часто в течение последнего месяца у Вас "
                         f"была слабая струя мочи?", reply_markup=keyboard)


async def answer3_chosen(message: types.Message, state: FSMContext):
    if message.text.lower() not in IPSS_answers:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer3=message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in IPSS_answers:
        keyboard.add(answer)
    await state.set_state(Rating.waiting_for_answer_4.state)
    await message.answer(f"Как часто в течение последнего месяца "
                         f"Вам приходилось натуживаться, чтобы начать "
                         f"мочеиспускание?", reply_markup=keyboard)


async def answer4_chosen(message: types.Message, state: FSMContext):
    if message.text.lower() not in IPSS_answers:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer4=message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in IPSS_answers:
        keyboard.add(answer)
    await state.set_state(Rating.waiting_for_answer_5.state)
    await message.answer(f"Как часто в течение последнего месяца у Вас "
                         f"была потребность мочиться чаще, чем через 2 "
                         f"часа после последнего мочеиспускания?", reply_markup=keyboard)


async def answer5_chosen(message: types.Message, state: FSMContext):
    if message.text.lower() not in IPSS_answers:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer5=message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in IPSS_answers:
        keyboard.add(answer)
    await state.set_state(Rating.waiting_for_answer_6.state)
    await message.answer(f"Как часто в течение последнего месяца "
                         f"Вам было трудно временно воздержаться"
                         f" от мочеиспускания?", reply_markup=keyboard)


async def answer6_chosen(message: types.Message, state: FSMContext):
    if message.text.lower() not in IPSS_answers:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer6=message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in IPSS_answers_last:
        keyboard.add(answer)
    await state.set_state(Rating.waiting_for_answer_7.state)
    await message.answer(f"В течение последнего месяца сколько раз Вы "
                         f"обычно встаете с постели, чтобы помочиться, "
                         f"после того, как легли спать, до момента, когда "
                         f"вам приходится вставать утром?", reply_markup=keyboard)


async def answer7_chosen(message: types.Message, state: FSMContext):
    if message.text.lower() not in IPSS_answers_last:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer7=message.text.lower())

    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for answer in QoL_answers:
        keyboard.add(answer)
    await state.set_state(Rating.waiting_for_answer_8.state)
    await message.answer(f"Как бы Вы отнеслись к тому, если бы Вам пришлось мириться с имеющимися у Вас "
                         f"урологическими проблемами до конца жизни?", reply_markup=keyboard)


async def answer8_chosen(message: types.Message, state: FSMContext):
    suma = 0
    symptomatology = ''
    if message.text.lower() not in QoL_answers:
        await message.answer("Пожалуйста, выберите ответ, используя клавиатуру ниже.")
        return
    await state.update_data(chosen_answer8=message.text.lower())

    user_data = await state.get_data()

    for num in range(1, 7):
        suma += IPSS_answers[user_data['chosen_answer' + str(num)]]

    result = IPSS_answers_last[user_data['chosen_answer7']] + suma

    result_1 = QoL_answers[user_data['chosen_answer8']]

    if 0 <= result < 8:
        symptomatology = 'похоже, у Вас всё хорошо, но не забывайте о необходимости диспансеризации!'

    if 7 < result < 20:
        symptomatology = 'Хм, советуем Вам внимательно следить за вашим здоровьем и обратиться за консультацией к специалисту.'

    if 19 < result < 36:
        symptomatology = 'Если Вы уверены в правильности Ваших ответов, советуем Вам в срочном порядке записаться к ' \
                         'специалисту.'

    await message.answer(
        f"Ваш результат: {result} баллов из 35\n"
        f"{symptomatology}"
        , reply_markup=types.ReplyKeyboardRemove())
    await message.answer("Результаты данного теста не являются диагнозом, для постановки точного диагноза и получения "
                         "рекомендаций по возможному лечению Вам необходимо обратиться к врачу.")
    await state.finish()

    await commands.update_user_qol(message.from_user.id, result_1)

    await commands.update_user_ipss(message.from_user.id, result)
    # keyboard = types.InlineKeyboardMarkup()
    # keyboard.add(types.InlineKeyboardButton(text="Подписаться", callback_data="random_value"))
    # await message.answer(
    #     "Благодарим за прохождение нашего экспресс-теста. Надеемся, в процессе у вас возник интерес к слежению за "
    #     "своим здоровьем, поэтому предлагаем оставить любые контактные данные, чтобы мы могли высылать вам "
    #     "эксклюзивные предложения о лечебных услугах наших партнёрских медицинских клиник.",
    #     reply_markup=keyboard)


async def send_random_value(callback: types.CallbackQuery):
    user = await commands.select_user(callback.from_user.id)
    if user.subscribed is not True:
        await commands.update_user_sub(callback.from_user.id, True)
        await callback.message.answer("Теперь я смогу делиться с Вами полезной информацией, эксклюзивными "
                                      "предложениями наших партнёров и последними новостями проекта.")
    else:
        await callback.message.answer("Вы уже оформили подписку")
    await callback.answer()


async def send_num(callback: types.CallbackQuery):
    await callback.answer()


async def send_word_3(callback: types.CallbackQuery):
    await callback.answer()
    await commands.update_user_gen(callback.from_user.id, 'M')
    buttons_2 = [
        types.InlineKeyboardButton(text="0-14", callback_data="age_0"),
        types.InlineKeyboardButton(text="14-35", callback_data="age_14"),
        types.InlineKeyboardButton(text="35-50", callback_data="age_35"),
        types.InlineKeyboardButton(text="50+", callback_data="age_50"),
    ]

    keyboard_2 = types.InlineKeyboardMarkup(row_width=2)
    keyboard_2.add(*buttons_2)

    await callback.message.answer("Цифра", reply_markup=keyboard_2)


async def send_word_2(callback: types.CallbackQuery):
    await callback.answer()
    await commands.update_user_gen(callback.from_user.id, 'W')
    await callback.message.answer("Мы крайне рады, что Вы проявляете интерес к теме мужского здоровья. Мы также будем "
                                  "делиться с Вами полезной информацией, однако если Вы зарегистрировались с целью "
                                  "помочь Вашему партнёру, пожалуйста, зарегистрируйте и его тоже, так мы сможем "
                                  "присылать ему информацию напрямую.")


async def send_word_1(callback: types.CallbackQuery):
    age = ''
    await callback.answer()
    action = callback.data.split("_")[1]
    if action == '0':
        age = '0-14'
    if action == '14':
        age = '14-35'
    if action == '35':
        age = '35-50'
    if action == '50':
        age = '50+'
    await commands.update_user_age(callback.from_user.id, age)
    await callback.message.answer("Отлично, давайте начнём")

    buttons_3 = [
        types.InlineKeyboardButton(text="Опрос", callback_data="quiz"),
        types.InlineKeyboardButton(text="Записаться на приём", callback_data="info"),
        types.InlineKeyboardButton(text="Подписаться",
                                   callback_data="sub"),
        types.InlineKeyboardButton(text="Info", callback_data="info_us"),
    ]
    keyboard_3 = types.InlineKeyboardMarkup(row_width=2)
    keyboard_3.add(*buttons_3)

    await callback.message.answer(f'Вот, что я умею:\n'
                                  f'Сейчас Вы можете:\n'
                                  f'Пройти опрос, принятый урологами во всём мире как золотой стандарт.\n'
                                  f'Подписаться на информационную рассылку.\n'
                                  f'Узнать, как и куда записаться к специалисту.\n'
                                  f'Прочитать дополнительную информацию обо мне, проекте и наших правилах.',
                                  reply_markup=keyboard_3)


async def quiz(callback: types.CallbackQuery, state: FSMContext):
    await state.finish()
    await callback.answer()
    await callback.message.answer(
        "Правила:\nВам будет представлено всего 8 вопросов с выбором ответа.Это около 5-ти минут "
        "Вашего времени.\nВнимательно читайте сами вопросы и варианты ответов. Точность результата "
        "зависит от честности Ваших ответов.")
    await answer_start(callback, state)


async def information(callback: types.CallbackQuery):
    await callback.answer()
    await callback.message.answer("Сейчас вы можете записаться на консультацию к урологу в Гос. Учреждение:\nна "
                                  "сайте <a href='https://www.mos.ru/services/zapis-k-vrachu/?ysclid=lj5zq8735o72184216'>mos.ru</a> или в приложении <a href='https://emias.info/?ysclid=lj600tb0o2677251089'>Емиас</a>. Чтобы получить информацию о "
                                  "других возможностях, Вам необходимо подписаться на нашу еженедельную "
                                  "информационную рассылку", parse_mode="HTML")


async def information_us(callback: types.CallbackQuery):
    await callback.answer()
    await callback.message.answer("""
    Проект:
Сейчас наши инженеры и врачи совместно трудятся над разработкой сети крайне полезных устройств. Благодаря им доступ к быстрому исследованию качества мочеиспускания станет бесплатным, простым и общедоступным.
Чуть позже тут будет ссылка на наш сайт.
Если хотите быть в курсе- подпишитесь на рассылку.

Про опрос:
В основу опроса лег адаптированный перевод признанного во всём мире индекса симптомов при заболеваниях простаты (IPSS) и шкалы качества жизни (QoL).
Оригинал: Barry, M.J., Fowler, F.J., O'leary, M.P., Bruskewitz, R. C., Holtgrewe, H. L., Mebust, W. K., & Cockett, A. T. K. (2017). The American Urological Association Symptom Index for Benign Prostatic Hyperplasia. The Journal of Urology, 197(2), S189-S197. doi:10.1016/j.juro.2016.10.071

Контакты:
Если захотите с нами связаться, или возникли проблемы с ботом-пишите по этому адресу:
uroflowbmt@gmail.com

Взаимодействуя с ботом, вы:
    1.  Добровольно соглашаетесь на использование вашего имени пользователя телеграмм для работы бота. 
    2. Подтверждаете, что осознаёте, что опрос не является медицинским обследованием, Вы не являетесь пациентом, а результат не является диагнозом или рекомендацией к лечению.
    3. Обязуетесь не предоставлять никаких персональных данных, поскольку осознаёте, что для работы бота они не требуются.
    4. Подтверждаете, свою исключительную ответственность за состояние своего здоровья.
    5. Соглашаетесь, что любая информация о возможный патологиях, представленная в этом боте не является диагнозом.
    6. Полностью осознаёте, что для постановки диагноза и получения рекомендаций по возможному лечению Вам необходимо обратиться к врачу.
    7. Подтверждаете, что все Ваши действия и решения, особенно в отношении вашего здоровья, после взаимодействия с ботом являются исключительно Вашей инициативой.

В случае несогласия с правилами использования вы имеете право в любой момент прервать работу бота и отправить запрос на удаление вашей учётной записи из БД бота.

С надеждой на здоровое будущее нации,
Ваш бот-помощник.
                                  """)


def register_handlers_answer(dp: Dispatcher):
    dp.register_message_handler(cmd_start, commands="start")
    dp.register_callback_query_handler(callback=send_num, text="num")
    dp.register_callback_query_handler(send_word_1, Text(startswith="age_"))
    dp.register_callback_query_handler(callback=send_word_2, text="word_2")
    dp.register_callback_query_handler(callback=send_word_3, text="word_3")
    dp.register_callback_query_handler(callback=quiz, text="quiz")
    dp.register_callback_query_handler(callback=information, text="info")
    dp.register_callback_query_handler(callback=information_us, text="info_us")
    dp.register_message_handler(answer1_chosen, state=Rating.waiting_for_answer_1, )
    dp.register_message_handler(answer2_chosen, state=Rating.waiting_for_answer_2)
    dp.register_message_handler(answer3_chosen, state=Rating.waiting_for_answer_3)
    dp.register_message_handler(answer4_chosen, state=Rating.waiting_for_answer_4)
    dp.register_message_handler(answer5_chosen, state=Rating.waiting_for_answer_5)
    dp.register_message_handler(answer6_chosen, state=Rating.waiting_for_answer_6)
    dp.register_message_handler(answer7_chosen, state=Rating.waiting_for_answer_7)
    dp.register_message_handler(answer8_chosen, state=Rating.waiting_for_answer_8)
    dp.register_callback_query_handler(callback=send_random_value, text="sub")
